using System;

using Raccoom.Xml;
using System.Xml;
using System.Xml.XPath;

namespace umbracoRss.BusinessLogic
{
    /// <summary>
    /// Summary description for rssInstance.
    /// </summary>
    public sealed class RssInstance
    {
        // Rss definitions
        private int _id;
        private string _title = "";
        private int _ttl = 60;
        private string _copyright = "";
        private string _category = "";
        private string _url = "";
        private RssItem[] _items;
        private XmlNode _xmlDef;

        // Source definitions
        private string _documentTypeFilterAlias = "";
        private int _documentId = 0;
        private bool _fullPath = false;
        private string _propertyTypeAlias = "";
        private string _filterValue = "";
        private string _descriptionSourceAlias = "";

        private string _author = "";
        private string _pubdatefield = "";

        public int Id
        {
            get { return _id; }
        }
        public string Author
        {
            get { return _author; }
            set
            {
                Data.UpdateValue(_xmlDef.SelectSingleNode("author"), value);
                _author = value;
            }
        }
        public string Pubdatefield
        {
            get { return _pubdatefield; }
            set
            {
                Data.UpdateValue(_xmlDef.SelectSingleNode("pubdatefield"), value);
                _pubdatefield = value;
            }
        }
        public string Title
        {
            get { return _title; }
            set
            {
                Data.UpdateValue(_xmlDef.SelectSingleNode("title"), value);
                _title = value;
            }
        }
        public int DocumentId
        {
            get { return _documentId; }
            set
            {
                Data.UpdateValue(_xmlDef.SelectSingleNode("documentId"), value.ToString());
                _documentId = value;
            }
        }
        public string Url
        {
            get { return _url; }
            set
            {
                Data.UpdateValue(_xmlDef.SelectSingleNode("url"), value);
                _url = value;
            }
        }
        public int TTL
        {
            get { return _ttl; }
            set
            {
                Data.UpdateValue(_xmlDef.SelectSingleNode("ttl"), value.ToString());
                _ttl = value;
            }
        }
        public string Copyright
        {
            get { return _copyright; }
            set
            {
                Data.UpdateValue(_xmlDef.SelectSingleNode("copyright"), value);
                _copyright = value;
            }
        }
        public string Category
        {
            get { return _category; }
            set
            {
                Data.UpdateValue(_xmlDef.SelectSingleNode("category"), value);
                _category = value;
            }
        }
        public bool FullPath
        {
            get { return _fullPath; }
            set
            {
                Data.UpdateValue(_xmlDef.SelectSingleNode("fullPath"), value.ToString());
                _fullPath = value;
            }
        }
        public string PropertyTypeAlias
        {
            get { return _propertyTypeAlias; }
            set
            {
                Data.UpdateValue(_xmlDef.SelectSingleNode("propertyTypeFilterAlias"), value);
                _propertyTypeAlias = value;
            }
        }
        public string DocumentTypeAlias
        {
            get { return _documentTypeFilterAlias; }
            set
            {
                Data.UpdateValue(_xmlDef.SelectSingleNode("documentTypeFilterAlias"), value);
                _documentTypeFilterAlias = value;
            }
        }
        public string DescriptionSourceAlias
        {
            get { return _descriptionSourceAlias; }
            set
            {
                Data.UpdateValue(_xmlDef.SelectSingleNode("descriptionSourceAlias"), value);
                _descriptionSourceAlias = value;
            }
        }
        public string FilterValue
        {
            get { return _filterValue; }
            set
            {
                Data.UpdateValue(_xmlDef.SelectSingleNode("filterValue"), value);
                _filterValue = value;
            }
        }

        public RssItem[] Items
        {
            get { return _items; }
        }


        public RssInstance(int Id)
        {
            _id = Id;
            populate();
        }

        private void populate()
        {
            XmlNode n = Data.GetFromId(_id);
            if (n != null)
            {
                _category = umbraco.xmlHelper.GetNodeValue(n.SelectSingleNode("category"));
                _copyright = umbraco.xmlHelper.GetNodeValue(n.SelectSingleNode("copyright"));
                _author = umbraco.xmlHelper.GetNodeValue(n.SelectSingleNode("author"));
                _descriptionSourceAlias = umbraco.xmlHelper.GetNodeValue(n.SelectSingleNode("descriptionSourceAlias"));
                _pubdatefield = umbraco.xmlHelper.GetNodeValue(n.SelectSingleNode("pubdatefield"));
                _documentId = int.Parse(umbraco.xmlHelper.GetNodeValue(n.SelectSingleNode("documentId")));
                _documentTypeFilterAlias = umbraco.xmlHelper.GetNodeValue(n.SelectSingleNode("documentTypeFilterAlias"));
                _filterValue = umbraco.xmlHelper.GetNodeValue(n.SelectSingleNode("filterValue"));
                _fullPath = bool.Parse(umbraco.xmlHelper.GetNodeValue(n.SelectSingleNode("fullPath")));
                _propertyTypeAlias = umbraco.xmlHelper.GetNodeValue(n.SelectSingleNode("propertyTypeFilterAlias"));
                _title = umbraco.xmlHelper.GetNodeValue(n.SelectSingleNode("title"));
                _ttl = int.Parse(umbraco.xmlHelper.GetNodeValue(n.SelectSingleNode("ttl")));
                _url = umbraco.xmlHelper.GetNodeValue(n.SelectSingleNode("url"));

                initItems();
            }
        }

        public static RssInstance[] GetAll()
        {
            XmlNodeList nList = Data.Source.SelectNodes("/umbracoRss/instances/instance");
            RssInstance[] retVal = new RssInstance[nList.Count];
            for (int i = 0; i < nList.Count; i++)
                retVal[i] = new RssInstance(int.Parse(nList[i].Attributes.GetNamedItem("id").Value));

            return retVal;
        }

        private void initItems()
        {
            // Get all contents and cast to an DOM Node
            XmlNode n = ((IHasXmlNode)umbraco.library.GetXmlNodeById(_documentId.ToString()).Current).GetNode();
            XPathNavigator nav = n.CreateNavigator();

            // Make xpath query
            string query = "";
            if (_documentTypeFilterAlias != "")
                query = " @nodeTypeAlias = '" + _documentTypeFilterAlias + "'";
            if (_propertyTypeAlias != "" && _filterValue != "")
            {
                // Check if we already have started adjusting our query
                if (query != "")
                    query += " and";

                query += " data [@alias = '" + _propertyTypeAlias + "'] = '" + _filterValue + "'";
            }
            if (query != "")
                query = "[" + query + "]";

            // Get contents
            if (_fullPath)
                query = "./descendant::node" + query;
            else
                query = "./node" + query;

            XPathExpression exp = nav.Compile(query);
            if (_pubdatefield != "")
            {
                exp.AddSort("data [@alias = '" + _pubdatefield + "']", XmlSortOrder.Descending, XmlCaseOrder.None, "", XmlDataType.Text);
            }
            else
            {
                exp.AddSort("@updateDate", XmlSortOrder.Descending, XmlCaseOrder.None, "", XmlDataType.Text);
            }


            string currentServerName = "http://" + System.Web.HttpContext.Current.Request.ServerVariables["SERVER_NAME"];

            XPathNodeIterator it = nav.Select(exp);
            int numberOfItems = it.Count;
            if (numberOfItems > 20)
                numberOfItems = 20;

            _items = new RssItem[numberOfItems];
            int i = 0;
            while (it.MoveNext() && i < numberOfItems)
            {
                XmlNode xmlItem = ((IHasXmlNode)it.Current).GetNode();

                RssItem tempList = new RssItem();

                // metadata
                if (_author != "")
                {
                    tempList.Author = _author;
                }
                else
                {
                    tempList.Author = xmlItem.Attributes.GetNamedItem("writerName").Value;
                }

                tempList.Title = xmlItem.Attributes.GetNamedItem("nodeName").Value;
                if (_pubdatefield != "")
                {
                    DateTime dtPub = DateTime.Parse(xmlItem.Attributes.GetNamedItem("updateDate").Value);
                    try
                    {
                        XmlNode pubdatefieldNode = xmlItem.SelectSingleNode("data [@alias = '" + _pubdatefield + "']");
                        if (pubdatefieldNode != null)
                            tempList.PubDate = DateTime.Parse(umbraco.xmlHelper.GetNodeValue(pubdatefieldNode));
                    }
                    catch (Exception ex)
                    {
                        umbraco.BusinessLogic.Log.Add(umbraco.BusinessLogic.LogTypes.Error, _documentId, ex.ToString());
                    }
                }
                else
                {
                    tempList.PubDate = DateTime.Parse(xmlItem.Attributes.GetNamedItem("updateDate").Value);
                }
                tempList.Link = currentServerName + umbraco.library.NiceUrl(int.Parse(xmlItem.Attributes.GetNamedItem("id").Value));

                // description
                XmlNode description = xmlItem.SelectSingleNode("data [@alias = '" + _descriptionSourceAlias + "']");
                if (description != null)
                    tempList.Description = umbraco.xmlHelper.GetNodeValue(description);
                _items[i] = tempList;
                i++;
            }

            // Xml Definition object
            _xmlDef = Data.GetFromId(Id);
        }
    }
}
